import pandas as pd
import numpy as np
from sklearn.preprocessing import MinMaxScaler
import re


def load_data(filename):
    """
    读取Excel文件
    """
    try:
        df = pd.read_excel(filename, engine='openpyxl')
        print(f"成功读取文件: {filename}")
        return df
    except Exception as e:
        print(f"读取文件失败: {str(e)}")
        return None


def check_data_shape(df):
    """
    输出数据形状
    """
    print(f"数据形状: {df.shape}")


def check_duplicates(df, columns):
    """
    检查指定列的重复值
    """
    print("\n重复值检查:")
    for col in columns:
        duplicate_count = df[col].duplicated().sum()
        print(f"{col} 列的重复值数量: {duplicate_count}")


def display_first_rows(df, n=5):
    """
    展示数据前n行
    """
    print(f"\n数据前{n}行:")
    print(df.head(n))


def clean_data(df):
    """
    数据清洗和调整
    """
    print("\n正在进行数据清洗...")

    # 创建数据副本
    df_clean = df.copy()

    # 检查缺失值
    print("缺失值统计:")
    print(df_clean.isnull().sum())

    # 处理数值型变量中的特殊字符
    numeric_columns = ['累计股息(%)', '年均股息(%)', '分红次数', '融资总额(亿元)']

    for col in numeric_columns:
        if col in df_clean.columns:
            # 移除百分号、逗号等特殊字符
            df_clean[col] = df_clean[col].astype(str).str.replace('%', '', regex=False)
            df_clean[col] = df_clean[col].str.replace(',', '', regex=False)
            df_clean[col] = df_clean[col].str.replace('--', '0', regex=False)
            df_clean[col] = df_clean[col].str.replace('-', '0', regex=False)

            # 转换为数值型
            df_clean[col] = pd.to_numeric(df_clean[col], errors='coerce')

    # 填充缺失值
    df_clean[numeric_columns] = df_clean[numeric_columns].fillna(0)

    return df_clean


def process_listing_date(df):
    """
    处理上市日期，提取年、月、日变量
    """
    print("\n正在处理上市日期...")

    df_processed = df.copy()

    # 确保上市日期为字符串类型
    df_processed['上市日期'] = df_processed['上市日期'].astype(str)

    # 提取年、月、日
    df_processed['上市年份'] = df_processed['上市日期'].str.extract(r'(\d{4})')
    df_processed['上市月份'] = df_processed['上市日期'].str.extract(r'(\d{1,2})[-/](\d{1,2})')[1]
    df_processed['上市日'] = df_processed['上市日期'].str.extract(r'(\d{1,2})$')

    # 转换为数值型
    date_columns = ['上市年份', '上市月份', '上市日']
    for col in date_columns:
        df_processed[col] = pd.to_numeric(df_processed[col], errors='coerce')

    print("上市日期处理完成")
    return df_processed


def normalize_numeric_data(df):
    """
    对数值型变量进行归一化处理
    """
    print("\n正在进行数据归一化...")

    # 数值型变量列表
    numeric_columns = ['累计股息(%)', '年均股息(%)', '分红次数', '融资总额(亿元)']

    # 检查这些列是否存在
    existing_columns = [col for col in numeric_columns if col in df.columns]

    if not existing_columns:
        print("没有找到数值型变量进行归一化")
        return df, pd.DataFrame()

    # 创建归一化器
    scaler = MinMaxScaler()

    # 进行归一化
    normalized_data = scaler.fit_transform(df[existing_columns])

    # 创建归一化后的DataFrame
    normalized_df = pd.DataFrame(
        normalized_data,
        columns=[f'{col}_归一化' for col in existing_columns]
    )

    print("数据归一化完成")
    return df, normalized_df


def main():
    # 读取数据
    input_file = "新浪财经历史分红数据.xlsx"
    df = load_data(input_file)

    if df is None:
        print("无法读取数据文件，请先运行爬虫程序")
        return

    # 任务2：输出数据形状和重复值检查
    check_data_shape(df)
    check_duplicates(df, ['代码', '名称', '详细'])

    # 任务3：展示前5行并调整数据
    display_first_rows(df, 5)
    df_clean = clean_data(df)

    # 任务4：处理上市日期
    df_processed = process_listing_date(df_clean)

    # 任务5：数值型变量归一化
    df_final, normalized_df = normalize_numeric_data(df_processed)

    # 横向合并原数据和归一化数据
    if not normalized_df.empty:
        df_final = pd.concat([df_final, normalized_df], axis=1)

    # 展示处理后的数据
    print("\n处理后的数据前5行:")
    print(df_final.head())

    # 任务6：保存预处理后的数据
    output_file = "新浪财经历史分红数据_预处理.xlsx"
    df_final.to_excel(output_file, index=False, engine='openpyxl')
    print(f"\n预处理后的数据已保存到: {output_file}")

    # 输出最终数据形状
    print(f"最终数据形状: {df_final.shape}")


if __name__ == "__main__":
    main()
